#include <iostream>
#include <memory>
#include <fstream>
#include "HttpServer.hpp"
#include "Util.hpp"

#define ROOT "./wwwroot"
#define HOMEPAGE "index.html"

void Usage(std::string proc)
{
    std::cout << "\nUsage: " << proc << " port\n" << std::endl;
}

void HttpHandler(int sock)
{
    // 1.读取请求
    char buffer[10240];
    ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0);
    if (s > 0)
        buffer[s] = 0;
    std::cout << buffer << "\n-----------------------------------\n" << std::endl;

    // // 2.下面是业务处理部分,需要对读取到的报文进行解包,然后构建应答
    // // 2.1 构建简单的应答
    // std::string HttpResponse = "HTTP/1.1 200 ok\r\n";  // 状态行
    // HttpResponse += "\r\n"; // 空间
    // HttpResponse += "<html><h3>hello Http!<!h3><!html>";   // 构建一个简单的网页
    // send(sock, HttpResponse.c_str(), HttpResponse.size(), 0);   

    // 2.2 构建一个复杂一些的应答
    std::vector<std::string> vline;
    Util::cutString(buffer, "\n", &vline);   // 把请求分解成一行一行的
    
    std::vector<std::string> block; // 解析出url中的路径
    Util::cutString(vline[0], " ", &block);   // 第一行 -> 请求行中的第二个参数就是路径

    std::string path = block[1];  // 这就是路径,但是如果提交表单,GET方式 就是 路径?pwd=xx&password=xxx -> 解析
    std::string file; // 这里才是真正的路径文件
    auto pos = path.find('?');
    if (pos == std::string::npos)   file = path;
    else    file = path.substr(0, pos);

    std::string target = ROOT;  // target是我们真正要访问的路径, 这里ROOT代表网站的根目录
    if (file == "/")  // 这里如果你什么也没输入,那我就访问默认网页
        file += "index.html";  // 默认网页是 index.html
    target += file;  // 加上你指定的路径

    std::cout << target << std::endl;  // 打印一下访问的路径

    std::string content;  // 这个是从文件中读取的信息, 即我们构建应答的正文
    std::ifstream in(target);  // 用流的方式打开文件
    if (in.is_open())
    {
        std::string line;
        while (std::getline(in, line)) // 在文件中按行读取
        {
            content += line;  // 把读到的信息放到正文中
        }
        in.close();   // 读完之后关闭流
    }

    // 构建应答
    std::string HttpResponse;
    if (content.empty())  // 如果我们读到的内容是空
    {
        HttpResponse = "HTTP/1.1 302 Found\r\n";  // 状态行 没有找到
        // 请求报头
        HttpResponse += "Location: http://106.54.42.34:8080/a/b/404.html\r\n";  // 让他跳转到另一个页面  临时重定向
    }
    else  // 读到的内容不是空,那就给他返回去
    {
        HttpResponse = "HTTP/1.1 200 OK\r\n";  // 状态行, 找到了
        // 请求报头
        HttpResponse += ("Content-Type: text/html\r\n");  // 访问文件的类型
        HttpResponse += ("Content-Length:" + std::to_string(content.size()) + "\r\n");  // 应答正文的大小
        HttpResponse += ("Set-cookie: 这里是一个cookie\r\n");  // 这里提交表单的时候才给它cookie,你加密后再给他返回
    }
    HttpResponse += "\r\n";  // 添加空行
    HttpResponse += content;  // 把正文添加进去
    send(sock, HttpResponse.c_str(), HttpResponse.size(), 0);  // 把构建的应答发送过去
}

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(0);
    }

    uint16_t port = atoi(argv[1]);

    std::unique_ptr<HttpServer> src(new HttpServer(port, HttpHandler));
    src->start();
    return 0;
}